local io = require[[async-io]]
local async = require[[async]].new()
local stream = require[[stream]]
local state = require[[state]]

local sign = function(x) return (x < 0 and -1 or 1) end

local is = function(x) return function(y) return y == x end end
local always = function(x) return function() return x end end
local plus = function() return function(a, b) return a + b end end
local signed_sqr = function() return function(x) return x*x*sign(x) end end
local even = function() return function(x) return x % 2 == 0 end end
local zero_if_nil2 = function(f)
	return function(a, b)
		if b == nil
		then return 0
		else return f(a, b)
		end
	end
end
local prefix_print = function(prefix) return function(x) print(prefix .. x) end end
local prefix_print2 = function(prefix) return function(t, x) print(prefix .. x, "@" .. t) end end

io.install_default(async)
local button = stream.from_button_press()
local btn_a = button:filter(is('a')):map(always(1))
local btn_d = button:filter(is('d')):map(always(-1))
local btn_s = button:filter(is('s')):map(always(nil))
local pos = stream.merge(btn_a, btn_d, btn_s):scan(zero_if_nil2(plus()), 0)
local sspos = pos:map(signed_sqr())
local sepos = sspos:filter(even())
local ssspos = sspos:state(0)
local ssepos = sepos:state(0)
ssspos.on_change(prefix_print[[> ]])
ssepos.on_change(prefix_print[[= ]])
ssepos:sample(0.5).on_event(prefix_print2[[# ]])

async:run()

